public class Test43 {
    /**
     * 递归求解
     * @param number 个数
     * @param max 最大点
     */
    public static void printProbability(int number,int max){
        if (number < 1 || max <1){
            return;
        }
        int maxSum = number * max;
        int[] probabilities = new int[maxSum - number +1];
        probability(number,probabilities,max);

        double total = 1;
        //计算骰子的全排列
        for (int i = 0; i < number; i++) {
            total *= max;
        }

        //计算概率
        for (int i = number; i <= maxSum; i++) {
            double ratio = probabilities[i - number] / total;
            System.out.printf("%-8.4f", ratio);
        }

        System.out.println();


    }

    /**
     * @param number 骰子个数
     * @param probabilities 不同骰子数出现次数的计数数组
     * @param max 骰子最大值
     */
    public static void probability(int number,int[] probabilities,int max){
        for (int i = 1; i<= max;i++){//第一个骰子可能出现的点数
            probability(number,number,i,probabilities,max);
        }
    }

    /**
     * @param original 骰子的总数
     * @param current 剩余要处理的骰子
     * @param sum 前面的总和
     * @param probabilities 不同骰子数出现次数的计数数组
     * @param max 最大值
     */
    public static void probability(int original, int current, int sum, int[] probabilities, int max){
        //当处理到最后一个骰子的时候，就把和放入，次数++
        if (current == 1)probabilities[sum-original]++; //和为sum的点数，增加
        else {
            //处理剩下的骰子
            for (int i = 1;i<= max;i++){
                probability(original,current-1,sum+i,probabilities,max);
            }
        }
    }

    public static void printProbability2(int number,int max){
        if (number < 1 || max <1){
            return;
        }

        //定义一个二维数组
        int[][] probabilities = new int[2][max*number+1];
        //初始化数据
        for (int i = 0; i<max*number+1;i++){
            probabilities[0][i] = 0;
            probabilities[1][i] = 0;
        }

        //标记当前要使用的是第0个数组还是第1个数组
        int flag = 0;

        //抛出第一个骰子时出现的各种情况
        for (int i = 1; i<= max;i++){
            probabilities[flag][i] = 1;
        }

        //抛出其他骰子
        for(int k = 2;k<= number;k++){
            // 如果抛出了k个骰子，那么和为[0, k-1]的出现次数为0
            for (int i = 1; i<k;i++){
                probabilities[1-flag][i] = 0;
            }
            //抛出k个骰子所有可能的和
            for(int j = k; j<=number*max;j++){
                probabilities[1-flag][j] = 0; //清0
                for (int m = 1; m<= j && m<=max;m++){
                    //求出当前数组可能出现的和
                    probabilities[1-flag][j] += probabilities[flag][j-m];
                }
            }
            flag = 1-flag;
        }
        double total= 1;
        for (int i = 0;i<number;i++) total *= max;
        int maxSum = number*max;
        for (int i = number;i<= maxSum;i++){
            double ratio = probabilities[flag][i] / total;
            System.out.printf("%-8.4f",ratio);
        }
    }
    public static void main(String[] args) {
        printProbability(3, 6);
        System.out.println();
        printProbability2(3, 6);
    }
}
